package cn.suimg.wechat.controller;

import cn.suimg.common.EncryptUtil;
import cn.suimg.common.JSONUtil;
import cn.suimg.common.response.ServerResponse;
import cn.suimg.wechat.bean.CorpWechat;
import cn.suimg.wechat.enmus.PublishMessageType;
import cn.suimg.wechat.service.CorpWechatService;
import cn.suimg.wechat.timer.FileAutoDeleteTimer;
import cn.suimg.wechat.util.CorpWechatUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;

/**
 * @author Suimg
 */
@RestController
@RequestMapping(value = "publish",produces="application/json;charset=UTF-8")
public class PublishController {

    /**
     * 支持的认证类型
     */
    private final List<String> allowedAuthTypes = Arrays.asList("b64","pkey");

    /**
     * 支持的消息类型
     */
    private final List<String> allowedMessageTypes = Arrays.asList("text","markdown","file","image");

    /**
     * 临时文件保存的位置
     */
    private final String tempFileDir = System.getProperty("java.io.tmpdir");

    @Resource
    private CorpWechatService corpWechatService;

    /**
     * 推送接收用户,目前设置的是所有人 后期更新定制推送
     */
    private final String receiveInfo = JSONUtil.toString(new HashMap<String, Object>(){{
        put("touser","@all");
        put("toparty","");
        put("totag","");
    }});


    @RequestMapping("{authType}/{authData}/{messageType}.do")
    public ServerResponse publishTextMessage(@PathVariable String authType, @PathVariable String authData, @PathVariable String messageType, String title, String content, MultipartFile file){
        //认证方式和消息类型校验
        if (!allowedAuthTypes.contains(authType))
            return ServerResponse.failed("auth type only supports " + Arrays.toString(allowedAuthTypes.toArray()));
        if(!allowedMessageTypes.contains(messageType))
            return ServerResponse.failed("message type only supports " + Arrays.toString(allowedMessageTypes.toArray()));

        String corpId = null,corpSecret = null,agentId = null;

        //base64 解码免配置推送
        if ("b64".equals(authType)) {
            try{
                String[] splitData = EncryptUtil.base64Decode(authData).split("\\|");
                corpId = splitData[0];
                corpSecret = splitData[1];
                agentId = splitData[2];
            }catch (RuntimeException e){
                return ServerResponse.failed("decode data error,please use Base64.encode(corpId|corpSecret|agentId) to encode data");
            }
        }

        //publish key 推送
        if("pkey".equals(authType)){
            CorpWechat tempCorpWechat = corpWechatService.getCorpWechatByPublishKey(authData);
            if(tempCorpWechat == null)
                return ServerResponse.failed("publish key not found!");
            corpId = tempCorpWechat.getCorpId();
            corpSecret = tempCorpWechat.getCorpSecret();
            agentId = tempCorpWechat.getAgentId();
        }

        //最后一遍校验推送需要的信息
        if(StringUtils.isBlank(corpId) || StringUtils.isBlank(corpSecret) || StringUtils.isBlank(agentId))
            return ServerResponse.failed("before publish check failed,some arg is blank");

        //解析消息推送类型
        PublishMessageType publishMessageType = PublishMessageType.parse(messageType);
        if(publishMessageType == null)
            return ServerResponse.failed("parse message type failed");

        //渲染推送的消息
        Object publishContent = "default publish content (config error)";
        if(publishMessageType == PublishMessageType.TextMessage)
            publishContent = title != null ? String.format("【%s】\n\n%s",title,content) : content;
        else if (publishMessageType == PublishMessageType.MarkdownMessage)
            publishContent = EncryptUtil.base64Decode(content);
        else if(publishMessageType == PublishMessageType.ImageMessage || publishMessageType == PublishMessageType.VideoMessage ||
                publishMessageType == PublishMessageType.VoiceMessage|| publishMessageType == PublishMessageType.FileMessage){
            File tempFile;
            try{
                if (file == null)
                    throw new IOException();
                tempFile = new File(tempFileDir, Objects.requireNonNull(file.getOriginalFilename()));
                FileCopyUtils.copy(file.getInputStream(),new FileOutputStream(tempFile));
                FileAutoDeleteTimer.commitFile(tempFile);
            }catch (NullPointerException | IOException e){
                return ServerResponse.failed("file upload error");
            }
            publishContent = tempFile;
        }
        CorpWechatUtil.getInstance(corpId,corpSecret,agentId).publishMessage(receiveInfo,publishMessageType,publishContent);
        return ServerResponse.success();
    }
}
